package com.mine.vioceplaylib.sound;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.mine.vioceplaylib.R;
import com.mine.vioceplaylib.utils.Tools;

import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class SoundPlayUtils {
    private ISoundCallback iSoundCallback;
    private static String TAG = SoundPlayUtils.class.getSimpleName();

    private static SoundPool mSoundPlayer;

    private static SoundPlayUtils soundPlayUtils = new SoundPlayUtils();
    private MediaPlayer mediaPlayer;

    public static SoundPlayUtils newInstance() {
        return soundPlayUtils;
    }

    private SoundPlayUtils() {
        init();
    }

    private HashMap<String, Sound> mAmounts = new HashMap<>();
    private final static int START_PLAY = 1;
    private Handler mVoiceHandler;
    private boolean mPlaying;

    private static final String NUM = "num";
    private static final String TO = "to";
    private static final String PL = "pl";
    private static final String LAST = "last";
    private static final String TEN = "ten";

    private Queue<Sound> mSoundQueue = new LinkedList<>();

    private Sound mCurrentSound;

    private AssetManager mAssetManager;

    private void init() {
        HandlerThread handlerThread = new HandlerThread("handler-thread");
        handlerThread.start();
        mVoiceHandler = new Handler(handlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == START_PLAY) {
                    soundPlayUtils.playNextSound();
                }
            }
        };
        Context context = Tools.getApplication().getApplicationContext();
        mAmounts.put("pl", new Sound(getMp3Duration(context, R.raw.pl) - 450, "pl"));
        mAmounts.put("0", new Sound(getMp3Duration(context, R.raw.t_0) - 750, "t_0"));
        mAmounts.put("1", new Sound(getMp3Duration(context, R.raw.t_1) - 750, "t_1"));
        mAmounts.put("2", new Sound(getMp3Duration(context, R.raw.t_2) - 750, "t_2"));
        mAmounts.put("3", new Sound(getMp3Duration(context, R.raw.t_3) - 750, "t_3"));
        mAmounts.put("4", new Sound(getMp3Duration(context, R.raw.t_4) - 750, "t_4"));
        mAmounts.put("5", new Sound(getMp3Duration(context, R.raw.t_5) - 750, "t_5"));
        mAmounts.put("6", new Sound(getMp3Duration(context, R.raw.t_6) - 750, "t_6"));
        mAmounts.put("7", new Sound(getMp3Duration(context, R.raw.t_7) - 750, "t_7"));
        mAmounts.put("8", new Sound(getMp3Duration(context, R.raw.t_8) - 750, "t_8"));
        mAmounts.put("9", new Sound(getMp3Duration(context, R.raw.t_9) - 750, "t_9"));
        mAmounts.put("a", new Sound(getMp3Duration(context, R.raw.t_a) - 750, "t_a"));
        mAmounts.put("b", new Sound(getMp3Duration(context, R.raw.t_b) - 750, "t_b"));
        mAmounts.put("c", new Sound(getMp3Duration(context, R.raw.t_c) - 750, "t_c"));
        mAmounts.put("d", new Sound(getMp3Duration(context, R.raw.t_d) - 750, "t_d"));
        mAmounts.put("e", new Sound(getMp3Duration(context, R.raw.t_e) - 750, "t_e"));
        mAmounts.put("f", new Sound(getMp3Duration(context, R.raw.t_f) - 750, "t_f"));
        mAmounts.put("g", new Sound(getMp3Duration(context, R.raw.t_g) - 750, "t_g"));
        mAmounts.put("h", new Sound(getMp3Duration(context, R.raw.t_h) - 750, "t_h"));
        mAmounts.put("i", new Sound(getMp3Duration(context, R.raw.t_i) - 750, "t_i"));
        mAmounts.put("j", new Sound(getMp3Duration(context, R.raw.t_j) - 750, "t_j"));
        mAmounts.put("k", new Sound(getMp3Duration(context, R.raw.t_k) - 750, "t_k"));
        mAmounts.put("l", new Sound(getMp3Duration(context, R.raw.t_l) - 750, "t_l"));
        mAmounts.put("m", new Sound(getMp3Duration(context, R.raw.t_m) - 750, "t_m"));
        mAmounts.put("n", new Sound(getMp3Duration(context, R.raw.t_n) - 750, "t_n"));
        mAmounts.put("o", new Sound(getMp3Duration(context, R.raw.t_o) - 750, "t_o"));
        mAmounts.put("q", new Sound(getMp3Duration(context, R.raw.t_q) - 750, "t_q"));
        mAmounts.put("r", new Sound(getMp3Duration(context, R.raw.t_r) - 750, "t_r"));
        mAmounts.put("s", new Sound(getMp3Duration(context, R.raw.t_s) - 750, "t_s"));
        mAmounts.put("t", new Sound(getMp3Duration(context, R.raw.t_t) - 750, "t_t"));
        mAmounts.put("u", new Sound(getMp3Duration(context, R.raw.t_u) - 750, "t_u"));
        mAmounts.put("v", new Sound(getMp3Duration(context, R.raw.t_v) - 750, "t_v"));
        mAmounts.put("w", new Sound(getMp3Duration(context, R.raw.t_w) - 750, "t_w"));
        mAmounts.put("x", new Sound(getMp3Duration(context, R.raw.t_x) - 750, "t_x"));
        mAmounts.put("y", new Sound(getMp3Duration(context, R.raw.t_y) - 750, "t_y"));
        mAmounts.put("z", new Sound(getMp3Duration(context, R.raw.t_z) - 750, "t_z"));

        mAmounts.put("ten", new Sound(getMp3Duration(context, R.raw.ten)-400, "ten"));

        mAmounts.put("to", new Sound(getMp3Duration(context, R.raw.to) - 700, "to"));
        mAmounts.put("num", new Sound(getMp3Duration(context, R.raw.num) - 600, "num"));
        mAmounts.put("last", new Sound(getMp3Duration(context, R.raw.last) - 500, "last"));

    }

    /**
     * 播放叫号语音
     *
     * @param jhSoundNum       排队号码
     * @param jhSoundWindowNum 处理业务的窗口号码
     */
    public void playJhSound(String jhSoundNum, String jhSoundWindowNum, ISoundCallback iSoundCallback) {
        this.iSoundCallback = iSoundCallback;
        if (TextUtils.isEmpty(jhSoundNum) || TextUtils.isEmpty(jhSoundWindowNum)) {
            return;
        }
        List<String> speech = new LinkedList<>();
        convertJhSound(speech, jhSoundNum, jhSoundWindowNum);
        playSeqSounds(speech);
    }

    private void playSeqSounds(List<String> soundsToPlay) {
        int length = soundsToPlay.size();
//        Log.i(TAG, "length start:" + length);
        if (mSoundQueue.size() == 0 && !mPlaying) {
            for (int j = 0; ; j++) {
//                Log.i(TAG, "length if for:" + length);
                if (j >= length) {
                    if (mVoiceHandler != null) {
                        mVoiceHandler.sendEmptyMessage(START_PLAY);
                    }
                    return;
                }
                String str = soundsToPlay.get(j);
                this.mSoundQueue.add(mAmounts.get(str));
//                Log.i(TAG, "mSoundQueue.add: " + str + " :ThreadName" + Thread.currentThread());
            }
        } else {
            for (int j = 0; ; j++) {
//                Log.i(TAG, "length if for:" + length);
                if (j >= length) {
                    return;
                }
                String str = soundsToPlay.get(j);
                this.mSoundQueue.add(mAmounts.get(str));
//                Log.i(TAG, "mSoundQueue.add: " + str + " :ThreadName" + Thread.currentThread());
            }
        }
    }

    private void playNextSound() {
        if (!mSoundQueue.isEmpty()) {
            mCurrentSound = mSoundQueue.poll();

            loadSound();
        } else {
            mPlaying = false;
//            Log.i(TAG, "startPlayer end" + " :ThreadName" + Thread.currentThread());
        }
    }

    @SuppressWarnings("deprecation")
    private void loadSound() {
        if (mSoundPlayer == null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                AudioAttributes attr = new AudioAttributes.Builder().
                        setLegacyStreamType(AudioManager.STREAM_MUSIC).build();
                mSoundPlayer = new SoundPool.Builder().setAudioAttributes(attr).setMaxStreams(3).build();
            } else {
                mSoundPlayer = new SoundPool(3, AudioManager.STREAM_MUSIC, 1);
            }
            mAssetManager = Tools.getApplication().getAssets();
            mSoundPlayer.setOnLoadCompleteListener((soundPool, sampleId, status) -> {
//                Log.i(TAG, "onLoadComplete sampleId: " + sampleId);
                if (status == 0) {
                    mPlaying = true;
                    int streamID = startPlayer(sampleId);
                    // play failed
                    if (streamID == 0) {
//                        Log.i(TAG, "streamID == 0");
                        if (iSoundCallback != null) {
                            iSoundCallback.failSoundPrint("播报失败语音:" + mCurrentSound.soundName + "-streamId:" + streamID);
                        }
                        releaseSound();
                        playNextSound();
                    } else {
                        try {
                            Thread.sleep(Math.abs(mCurrentSound.duration));
                            if (LAST.equals(mCurrentSound.soundName)) {
                                releaseSound();
                                if (iSoundCallback != null) {
                                    iSoundCallback.finishSoundPrint("播报" + mCurrentSound.soundName + "语音完毕");
                                }
                            }
                            playNextSound();
                        } catch (InterruptedException e) {
                            mPlaying = false;
                        }
                    }
                } else {
                    // load failed
                    Log.i(TAG, "status != 0");
                    releaseSound();
                }
            });
        }
        if (iSoundCallback != null && mCurrentSound != null) {
            iSoundCallback.startSoundPrint("当前播报叫号语音:" + mCurrentSound.soundName);
        }
        try {
            if (mCurrentSound != null) {
                AssetFileDescriptor afd = mAssetManager.openFd(mCurrentSound.soundName + ".mp3");
                mSoundPlayer.load(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(), 1);
            }
        } catch (Exception e) {
//            Log.i(TAG, "AssetFileDescriptor load IOException");
            playNextSound();
        }
    }

    private void releaseSound() {
//        Log.i(TAG, "releaseSound");
        mSoundPlayer.release();
        mSoundPlayer = null;
    }

    /**
     * 播放声音
     *
     * @param soundID 声音Id（序号）
     */
    public int startPlayer(int soundID) {
        return mSoundPlayer.play(soundID, 1, 1, 0, 0, 1);
    }

    private void convertJhSound(List<String> speech, String jhSoundNum, String jhSoundWindowNum) {
        speech.add(PL);
        //排队号码转换成单个字符并插入的speech队列中

        char[] jhSoundNumChars = jhSoundNum.toCharArray();
        for (char aChar : jhSoundNumChars) {
            speech.add(String.valueOf(aChar).toLowerCase());
        }

        speech.add(NUM);
        speech.add(TO);
        char[] jhSoundWidowNumChars = jhSoundWindowNum.toCharArray();
        int windowNumSize = jhSoundWidowNumChars.length;

        boolean isTenAdd = false;
        for (char jhSoundWidowNumChar : jhSoundWidowNumChars) {
            if (windowNumSize == 2) {
                String firstWindowNum = String.valueOf(jhSoundWidowNumChars[0]);
                String secondWindowNum = String.valueOf(jhSoundWidowNumChars[1]);
                if ("1".equals(firstWindowNum) && !isTenAdd) {
                    speech.add(TEN);
                    isTenAdd = true;
                } else if (!"0".equals(secondWindowNum)) {
                    addAudio(speech, jhSoundWidowNumChar);
                }
            } else {
                addAudio(speech, jhSoundWidowNumChar);
            }
        }
        Log.d("windowNumSize", "位数:" + windowNumSize + "-" + jhSoundWindowNum);

//        for (char aChar : jhSoundWidowNumChars) {
//            Log.e("bug",aChar+"测试");
//
////            speech.add(windowNumChar);
//        }
        speech.add(LAST);
    }

    private void addAudio(List<String> speech, char jhSoundWidowNumChar) {
        String windowNumChar = String.valueOf(jhSoundWidowNumChar);
        speech.add(windowNumChar);
    }


    private final class Sound {
        private int duration;
        private String soundName;

        private Sound(int time, String soundName) {
            this.duration = time;
            this.soundName = soundName;
        }
    }

    /**
     * 获取音频文件的时长
     */
    private int getMp3Duration(Context context, int rawId) {
        try {
            Uri uri = Uri.parse("android.resource://" + context.getPackageName() + "/" + rawId);
            if (mediaPlayer == null) {
                mediaPlayer = new MediaPlayer();
            }
            mediaPlayer.reset();
            mediaPlayer.setDataSource(context, uri);
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.prepare();
            return mediaPlayer.getDuration();
        } catch (IOException e) {
            e.printStackTrace();
            if (mediaPlayer != null) {
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }
        return 0;
    }
}